struct DXToVertex
{
   float3 Position	:POSITION;
   float3 Normal	:NORMAL;
   float2 Texture0	:TEXCOORD0;
   float2 TexBump	:TEXCOORD1;
};

struct VertexToPixel
{
    float4 Position     :POSITION;
    float3 Normal	:TEXCOORD0;
    float2 TexBump	:TEXCOORD1;
    float4 ReflectionMapPos :TEXCOORD2;    
    float4 RefractionMapPos :TEXCOORD3;
    float4 Pos3d    	:TEXCOORD4;
};

Texture reflectTex;
Texture refractTex;
Texture waterBumpTex;

sampler reflectSampler = sampler_state 
{
	texture = <reflectTex> ; 
	magfilter = LINEAR; 
	minfilter = LINEAR; 
	mipfilter = LINEAR; 
	AddressU = mirror; 
	AddressV = mirror;
};

sampler refractSampler = sampler_state 
{
	texture = <refractTex> ; 
	magfilter = LINEAR; 
	minfilter = LINEAR; 
	mipfilter = LINEAR; 
	AddressU = mirror; 
	AddressV = mirror;
};

sampler waterBumpSampler = sampler_state 
{
	texture = <waterBumpTex> ; 
	magfilter = LINEAR; 
	minfilter = LINEAR; 
	mipfilter = LINEAR; 
	//AddressU = mirror; 
	AddressV = mirror;
};

float4x4 xWorldViewProj;
float4x4 xReflectMatrix;
float4x4 xProjection;
float4x4 xWorld;

float4 xMaterialAmbient;
float4 xMaterialDiffuse;
float4 xMaterialSpecular;

float4 xLight;
float4 xLightPos;
float4 xLightAmbient;
float4 xLightDiffuse;
float4 xLightSpecular;

float4 xCamPosition;
float xTime;


VertexToPixel WaterVertexShader(DXToVertex In)
{
    VertexToPixel Output = (VertexToPixel) 0;
   
    Output.Normal = In.Normal.xyz;
	Output.Pos3d = float4(In.Position.xyz, 1);

	Output.Position = mul(Output.Pos3d, xWorldViewProj);
    Output.RefractionMapPos = Output.Position;
    Output.ReflectionMapPos = mul(Output.Pos3d, xReflectMatrix);

	Output.TexBump = In.Texture0 * 400.f + float2(0, 0.04f * xTime);
    
    return Output;    
}

float4 WaterPixelShader(VertexToPixel In) : COLOR0
{
	float2 reversedTexCoords = 0.9f * In.TexBump - float2(0, 0.1f * xTime);
	float4 waterBumpColor = tex2D(waterBumpSampler, In.TexBump);
	float4 waterBumpColor2 = tex2D(waterBumpSampler, reversedTexCoords);
    float2 bumping = 0.4f * (waterBumpColor.rg - 0.5f);
	float2 bumping2 = 0.4f * (waterBumpColor2.rg - 0.5f);

    float2 ProjectedTexCoords;
    ProjectedTexCoords.x = In.ReflectionMapPos.x / In.ReflectionMapPos.w / 2.0f + 0.5f;
    ProjectedTexCoords.y = -In.ReflectionMapPos.y / In.ReflectionMapPos.w / 2.0f + 0.5f;
    ProjectedTexCoords += bumping + bumping2;
    float4 Color = tex2D(reflectSampler, ProjectedTexCoords);
    
    float2 ProjectedRefrTexCoords;
    ProjectedRefrTexCoords.x = In.RefractionMapPos.x / In.RefractionMapPos.w / 2.0f + 0.5f;
    ProjectedRefrTexCoords.y = -In.RefractionMapPos.y / In.RefractionMapPos.w / 2.0f + 0.5f;
    ProjectedRefrTexCoords += bumping + bumping2;
    float4 refractiveColor = tex2D(refractSampler, ProjectedRefrTexCoords);
     
    float3 eyeVector = normalize(xCamPosition - In.Pos3d);
	float fresnelTerm;
	float3 normalVector;
	float4 combinedColor;
	
	if (xCamPosition.y > 0)
	{
		normalVector = float3(0, 1, 0);
		fresnelTerm = dot(eyeVector, normalVector);
		combinedColor = lerp(Color, refractiveColor, fresnelTerm);
	}
	else 
	{
		normalVector = float3(0, -1, 0);
		combinedColor = refractiveColor;
	}
     
    float4 dullColor = float4(0.0f, 0.0f, 0.0f, 0.0f);
    normalVector = (waterBumpColor2.rgb - 0.5f)*2.0f;
    Color = lerp(combinedColor, dullColor, 0.2f);

    return Color;
}

technique WaterTechnique
{
    pass Pass0
    {        
		AlphaBlendEnable = false;
		ZWriteEnable = true;  
		CullMode = none;

        VertexShader = compile vs_1_1 WaterVertexShader();
        PixelShader = compile ps_2_0 WaterPixelShader();
    }
}